package com.hs.biye.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hs.biye.annotation.AuthCheck;
import com.hs.biye.constant.MessageConstant;
import com.hs.biye.constant.ParameterCinstant;
import com.hs.biye.constant.RolerConstant;
import com.hs.biye.constant.regularConstant;
import com.hs.biye.excepction.BaseException;
import com.hs.biye.mapper.DepartmentMapper;
import com.hs.biye.mapper.RoomMapper;
import com.hs.biye.mapper.SalaryMapper;
import com.hs.biye.model.DTO.EmployeeRequest;
import com.hs.biye.model.VO.EmployeeVO;
import com.hs.biye.model.entity.*;
import com.hs.biye.model.entity.Employee;
import com.hs.biye.model.enums.GenderEnum;
import com.hs.biye.model.enums.RoomTypeEnum;
import com.hs.biye.model.reslut.ResultPage;
import com.hs.biye.service.EmployeeService;
import com.hs.biye.mapper.EmployeeMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author haoshuai
 * @description 针对表【Employee】的数据库操作Service实现
 * @createDate 2023-12-07 19:03:23
 */
@Service
@Slf4j
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee>
        implements EmployeeService {

    @Resource
    private EmployeeMapper employeeMapper;

    @Resource
    private DepartmentMapper departmentMapper;


    @Resource
    private SalaryMapper salaryMapper;

    @Resource
    private RoomMapper roomMapper;

    /**
     * 登录
     *
     * @param employeeRequest
     * @return
     */
    @Override
    public Employee login(EmployeeRequest employeeRequest) {

        String userAccount = employeeRequest.getUserAccount();
        String password = employeeRequest.getPassword();

        if (userAccount==null || password == null){
            throw new BaseException(MessageConstant.PAR_NOT_RIGHT);
        }
        if (userAccount.length() <ParameterCinstant.USER_ACCOUNT_MIN || userAccount.length() >ParameterCinstant.USER_ACCOUNT_MAX){
            throw new BaseException(MessageConstant.USER_ACCOUNT_LENGTH);
        }

        if (password.length() < ParameterCinstant.PASSWROD_MIN  || password.length() > ParameterCinstant.PASSWROD_MAX){
            throw new BaseException(MessageConstant.PASSWROD_LENGTH);
        }
        //1、根据用户名查询数据库中的数据
        QueryWrapper<Employee> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount", userAccount);
        Employee employee = getOne(queryWrapper);

        //2、处理各种异常情况（用户名不存在、密码不对、账号被锁定）
        if (employee == null) {
            //账号不存在
            log.info("密码错误");
            throw new BaseException(MessageConstant.ACCOUNT_NOT_FOUND);

        }

        //密码比对
        //  后期需要进行md5加密，然后再进行比对
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!password.equals(employee.getPassword())) {
            //密码错误
             throw new BaseException(MessageConstant.PASSWORD_ERROR);
        }

        //3、返回实体对象
        return employee;
    }


    /**
     * 根据id获取员工信息
     * @param id
     * @return
     */
    @Override
    public EmployeeVO getOneEmployee(Integer id) {
        if (id == null) {
            throw new BaseException(MessageConstant.PAR_NOT);
        }
        Employee employee = getById(id);
        if (employee == null) {
            throw new BaseException(MessageConstant.NOT_QUERY);
        }
        EmployeeVO employeeVO = new EmployeeVO();
        BeanUtils.copyProperties(employee, employeeVO);
        // 查询薪资和部门
        Department department = departmentMapper.selectById(employee.getDepartmentId());
        Salary salary = salaryMapper.selectOne(new QueryWrapper<Salary>()
                .eq("slarayId", employee.getSalaryType()));
        employeeVO.setSalary(salary.getTotal());
        employeeVO.setDepartmentName(department.getDepartmentName());
        employeeVO.setGender(GenderEnum.getValueByCode(employee.getGender()));
        return employeeVO;
    }



    /**
     * 分页查询
     * @param page
     * @param size
     * @return
     */
    @Override
    public ResultPage<EmployeeVO> getEmployee(Integer page, Integer size,EmployeeRequest employeeRequest) {
        IPage<Employee> page2 = new Page<>(page, size);
        LambdaQueryWrapper<Employee> queryWrapper = getQueryWrapper(employeeRequest);
        employeeMapper.selectPage(page2, queryWrapper);

        List<Employee> records = page2.getRecords();
        long total = page2.getTotal();
        long current = page2.getCurrent();
        long pages = page2.getPages();

        List<EmployeeVO> list = new ArrayList<>();
        records.forEach(item -> {
            EmployeeVO employeeVO = new EmployeeVO();
            BeanUtils.copyProperties(item, employeeVO);
            //查询薪资和部门
            if (item.getRoler().equals("user")){
                Department department = departmentMapper.selectById(item.getDepartmentId());
                employeeVO.setDepartmentName(department.getDepartmentName());
            }else {
                employeeVO.setDepartmentName("系统管理");
            }
            Salary salary = salaryMapper.selectById(item.getSalaryType());
            if (salary != null){
                employeeVO.setSalary(salary.getTotal());
            }else {
                employeeVO.setSalary(-1);
            }
            employeeVO.setGender(GenderEnum.getValueByCode(item.getGender()));
            list.add(employeeVO);

        });
        return ResultPage.success(list, total,current,pages);
    }




    /**
     * 添加员工
     * @param employee
     * @return
     */
    @Override
    @Transactional
    @AuthCheck(mustRole = RolerConstant.ADMIN)
    public boolean addEmployee(Employee employee) {
        if (verif(employee)) {
            throw new BaseException(MessageConstant.PAR_NOT);
        }
        //员工职务是主任就是该部门的负责人
        if (employee.getPosition().equals("主任")){
            //先判断该部门是否已经存在主任
            LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Employee::getPosition,"主任").eq(Employee::getDepartmentId,employee.getDepartmentId());
            Long count = employeeMapper.selectCount(queryWrapper);
            if (count != 0){
                throw new BaseException(MessageConstant.EXIST);
            }
            Department department = new Department();
            department.setDepartmentId(employee.getDepartmentId());
            //设置该主任为该部门的负责人
            department.setDepartmentLeaderId(employee.getEmployeeId());
            int i = departmentMapper.updateById(department);
        }
        return save(employee);
    }

    /**
     * 修改员工
     * @param employee
     * @return
     */
    @Override
    @Transactional
    @AuthCheck(mustRole = RolerConstant.ADMIN)
    public boolean updateEmployee(Employee employee) {
        if (verif(employee)) {
            throw new BaseException(MessageConstant.PAR_NOT);
        }
        //员工职务是主任就是该部门的负责人
        if (employee.getPosition().equals("主任")){
            //先判断该部门是否已经存在主任
            LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Employee::getPosition,"主任").eq(Employee::getDepartmentId,employee.getDepartmentId());
            Long count = employeeMapper.selectCount(queryWrapper);
            if (count != 0){
                throw new BaseException(MessageConstant.EXIST);
            }
            Department department = new Department();
            department.setDepartmentId(employee.getDepartmentId());
            //设置该主任为该部门的负责人
            department.setDepartmentLeaderId(employee.getEmployeeId());
            int i = departmentMapper.updateById(department);
        }
        return updateById(employee);
    }


    /**
     * 删除员工
     *
     * @param id
     * @return
     */
    @Override
    @AuthCheck(mustRole = RolerConstant.ADMIN)
    public boolean removeEmployee(Integer id) {
        if (id == null) {
            throw new BaseException(MessageConstant.PAR_NOT_RIGHT);
        }
        return removeById(id);
    }


    //根据部门id获取医生
    @Override
    public List<EmployeeVO> getEmployeeByDepId(Integer id) {
        if (id == null) {
            throw new BaseException(MessageConstant.PAR_NOT_RIGHT);
        }
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(Employee::getEmployeeId,Employee::getEmployeeName).eq(Employee::getDepartmentId,id);
        List<Employee> employees = employeeMapper.selectList(queryWrapper);
        List<EmployeeVO> res = new ArrayList<>();
        employees.forEach(item->{
            EmployeeVO employeeVO = new EmployeeVO();
            BeanUtils.copyProperties(item,employeeVO);
            res.add(employeeVO);
        });
        return res;
    }


    //根据部门id获取医生

    @Override
    public List<EmployeeVO> getEmployeeNotRoom(Integer id) {
        LambdaQueryWrapper<Room> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(Room::getDoctorId).eq(Room::getType, RoomTypeEnum.CONSULTING.getCode());
        List<Room> rooms = roomMapper.selectList(queryWrapper);
        List<String> collect = rooms.stream().map(i -> i.getDoctorId()).collect(Collectors.toList());

        LambdaQueryWrapper<Employee> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.select(Employee::getEmployeeId,Employee::getEmployeeName)
                        .notIn(Employee::getEmployeeId,collect).eq(Employee::getDepartmentId,id);
        List<Employee> employees = employeeMapper.selectList(queryWrapper1);

        List<EmployeeVO> res = new ArrayList<>();
        employees.forEach(item->{
            EmployeeVO employeeVO = new EmployeeVO();
            employeeVO.setEmployeeId(item.getEmployeeId());
            employeeVO.setEmployeeName(item.getEmployeeName());
            res.add(employeeVO);
        });

        return res;
    }

    @Override
    public List<EmployeeVO> getEmployeeNotRoom2(Integer id,Integer id2) {
        LambdaQueryWrapper<Room> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(Room::getDoctorId).eq(Room::getType, RoomTypeEnum.CONSULTING.getCode());
        List<Room> rooms = roomMapper.selectList(queryWrapper);
        List<String> collect = rooms.stream().map(i -> i.getDoctorId()).collect(Collectors.toList());

        LambdaQueryWrapper<Employee> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.select(Employee::getEmployeeId,Employee::getEmployeeName)
                .notIn(Employee::getEmployeeId,collect).eq(Employee::getDepartmentId,id);
        List<Employee> employees = employeeMapper.selectList(queryWrapper1);

        List<EmployeeVO> res = new ArrayList<>();
        employees.forEach(item->{
            EmployeeVO employeeVO = new EmployeeVO();
            employeeVO.setEmployeeId(item.getEmployeeId());
            employeeVO.setEmployeeName(item.getEmployeeName());
            res.add(employeeVO);
        });
        Employee employee = getById(id2);
        EmployeeVO employeeVO = new EmployeeVO();
        employeeVO.setEmployeeId(employee.getEmployeeId());
        employeeVO.setEmployeeName(employee.getEmployeeName());
        res.add(employeeVO);
        return res;
    }


    private LambdaQueryWrapper<Employee> getQueryWrapper(EmployeeRequest employeeRequest){

        LambdaQueryWrapper<Employee> employeeQueryWrapper = new LambdaQueryWrapper<>();

        Integer employeeId = employeeRequest.getEmployeeId();
        String name = employeeRequest.getEmployeeName();
        Integer gender = GenderEnum.getCodeByValue(employeeRequest.getGender());

        String userAccount = employeeRequest.getUserAccount();
        String position = employeeRequest.getPosition();


/*        //根据部门名称查询数据库获取id
        String departmentName = employeeRequest.getDepartmentName();
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(Department::getDepartmentId).eq(Department::getDepartmentName,departmentName);
        Department department = departmentMapper.selectOne(queryWrapper);
        Integer departmentID = department.getDepartmentId();*/

        Integer departmentId = employeeRequest.getDepartmentId();
        String roler = employeeRequest.getRoler();
        String phone = employeeRequest.getPhone();
        LocalDateTime createTime = employeeRequest.getCreateTime();
        LocalDateTime updateTime = employeeRequest.getUpdateTime();


        employeeQueryWrapper.eq(ObjectUtil.isNotEmpty(name),Employee::getEmployeeName,name);
        employeeQueryWrapper.eq(ObjectUtil.isNotEmpty(userAccount),Employee::getUserAccount,userAccount);
        employeeQueryWrapper.eq(ObjectUtil.isNotEmpty(phone),Employee::getPhone,phone);
        employeeQueryWrapper.eq(gender!=-1,Employee::getGender,gender);
        employeeQueryWrapper.eq(ObjectUtil.isNotEmpty(departmentId),Employee::getDepartmentId,departmentId);
        //排序
        // employeeQueryWrapper.orderBy(true,true,Employee::getCreateTime);

        return employeeQueryWrapper;
    }


    /**
     * 检验数据格式
     * @param employeeRequest
     * @return
     */
    private boolean verif(Employee employeeRequest){
        if (employeeRequest == null){
            return false;
        }
        String name = employeeRequest.getEmployeeName();
        Integer gender = employeeRequest.getGender();
        String userAccount = employeeRequest.getUserAccount();
        String position = employeeRequest.getPosition();
        String roler = employeeRequest.getRoler();
        Integer salaryType = employeeRequest.getSalaryType();
        LocalDate bithday = employeeRequest.getBithday();
        String phone = employeeRequest.getPhone();
        if (name.length()< ParameterCinstant.NAME_MIN || name.length() > ParameterCinstant.NAME_MAX ||
                ReUtil.isMatch(regularConstant.SPECIAL_CHAR,name)){
            return false;
        }
        if (!ReUtil.isMatch(regularConstant.PHONE,phone)){
            return false;
        }
        if (userAccount.length() <ParameterCinstant.USER_ACCOUNT_MIN || userAccount.length() >ParameterCinstant.USER_ACCOUNT_MAX){
            return false;
        }
        return ReUtil.isMatch(regularConstant.BITHDAY, bithday.toString());
    }


}




